package com.gqzmy.springboot3.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author 周小哥  gqzmy@163.com 2022/12/1 10:59
 */

//@Aspect
//@Component
public class AopAdvice {

	public static final Logger logger = LoggerFactory.getLogger(AopAdvice.class);

	@Pointcut("execution(* com.gqzmy.springboot3.mapper.*.*(..))")
	public void aopAdvice() {
	}

	@Before("aopAdvice()")
	public void doBefore(JoinPoint joinPoint) {
		logger.info(" 触发切面@Before 在方法前执行 ");
		Object target = joinPoint.getTarget();
		logger.info(" 触发切面@Before 目标对象: {} ", target);
		String targetMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
		logger.info(" 触发切面@Before 目标方法: {} ", targetMethod);
		Object[] args = joinPoint.getArgs();
		logger.info(" 触发切面@Before 传入参数: {} ", List.of(args));
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		logger.info(" 触发切面@Before 传入参数: {} ", List.of(methodSignature.getParameterNames()));
	}

	@After("aopAdvice()")
	public void doAfter(JoinPoint joinPoint) {
		logger.info(" 触发切面@After 在方法后执行 ");
	}

	@AfterReturning(value = "aopAdvice()", returning = "methodResult")
	public void doAfterReturning(JoinPoint joinPoint, Object methodResult) {
		logger.info(" 触发切面@AfterReturning 在方法执行后返回一个结果后执行 ");
		String targetMethod = joinPoint.getSignature().getDeclaringType() + "." + joinPoint.getSignature().getName();
		logger.info(" 触发切面@AfterReturning 目标方法: {} ", targetMethod);
		logger.info(" 触发切面@AfterReturning 返回值: {} ", methodResult);
	}

	@AfterThrowing(value = "aopAdvice()", throwing = "exception")
	public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
		logger.info(" 触发切面@AfterThrowing 在方法执行过程种抛出异常的时候执行 ");
		logger.info(" 触发切面@AfterThrowing Exception is : ", exception);
	}

	@Around("aopAdvice()")
	public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
		logger.info(" 触发切面@Around 环绕通知，可以在执行前后都使用 ");
		logger.info(" 触发切面@Around 环绕通知，前置 ");
		Object proceed = joinPoint.proceed();

		logger.info(" 触发切面@Around 环绕通知，后置 ");
		return proceed;
	}

}
